import { Table } from "./interface/table";

/**
 * @description table 页面操作方法封装
 * @param {Function} api 获取表格数据 api 方法 (非必传)
 * @param {Object} initParam 获取数据初始化参数 (非必传，默认为{})
 * @param {Boolean} isPageable 是否有分页 (非必传，默认为true)
 * @param {Function} dataCallBack 对后台返回的数据进行处理的方法 (非必传)
 * @param {Function} changeSearchParams 对查询前参数进行修改 (非必传)
 *
 * */
export const useTable = (
  api?: (params: any) => Promise<any>,
  initParam: object = {},
  isPageable: boolean = true,
  selectChange?: (data: any) => any,
  dataCallBack?: (data: any) => any,
  requestError?: (error: any) => void,
  changeSearchParams?: (data: any) => {}
) => {
  const state = reactive<Table.StateProps>({
    // 表格数据
    tableData: [],
    // 加载状态
    loading: false,
    // 下拉刷新
    pullToRefreshLoading: false,
    multipleIds: [],
    multipleSelection: [],
    checkFlag: [],
    // 分页数据
    pageable: {
      // 当前页数
      pageNum: 1,
      // 每页显示条数
      pageSize: 30,
      // 总条数
      total: 0,
      // 总页数
      sumPageNum: 1
    },
    // 查询参数(只包括查询)
    searchParam: {},
    // 初始化默认的查询参数
    searchInitParam: {},
    // 总参数(包含分页和查询参数)
    totalParam: {},
    loadingStatus: "more"
  });

  /**
   * @description 分页查询参数(只包括分页和表格字段排序,其他排序方式可自行配置)
   * */
  const pageParam = computed({
    get: () => {
      return {
        pageNum: state.pageable.pageNum,
        pageSize: state.pageable.pageSize
      };
    },
    set: (newVal: any) => {
      console.log("我是分页更新之后的值", newVal);
    }
  });

  /**
   * @description 获取表格数据
   * @param {boolean} flag 加载类型
   * @return void
   * */
  const getTableList = async (flag: "up" | "down" | "default" = "default") => {
    if (!api) return;
    try {
      // 先把初始化参数和分页参数放到总参数里面
      let params = Object.assign(state.totalParam, initParam, isPageable ? pageParam.value : {});
      // 是否在查询前需要修改查询参数
      if (changeSearchParams) {
        params = await changeSearchParams(params);
        if (!params) return;
      }
      if (flag === "down") {
        state.pullToRefreshLoading = true;
      }
      state.loading = true;
      // 调用接口获取数据
      let data = await api(params);

      // 对返回数据进行修改
      dataCallBack && (data = dataCallBack(data));

      // 获取返回参数
      const backData = (isPageable ? data?.records : data) ?? [];
      if (flag !== "up") {
        state.tableData = backData;
      } else {
        // 上拉刷新 添加数据
        state.tableData.push(...backData);
      }

      // 解构后台返回的分页数据 (如果有分页更新分页信息)
      if (isPageable) {
        const { total, size, current, pages } = data;
        updatePageable({ pageNum: current, pageSize: size, total, sumPageNum: pages });
      }
      state.multipleIds = [];
      state.multipleSelection = [];
      state.checkFlag = [];
      setTimeout(() => {
        state.loading = false;
        state.pullToRefreshLoading = false;
      }, 500);
    } catch (error) {
      console.log(error);
      state.loading = false;
      state.pullToRefreshLoading = false;
      state.multipleIds = [];
      state.checkFlag = [];
      state.multipleSelection = [];
      state.tableData = [];
      requestError && requestError(error);
    }
  };

  /**
   * @description 是否显示底部加载标识
   * @return void
   * */
  const displayLoadMore = computed(() => {
    const length = state.tableData.length;
    return length >= state.pageable.pageSize;
  });

  /**
   * @description 触底加载
   * @return void
   * */
  const bottomLoading = () => {
    const { pageNum, sumPageNum } = state.pageable;

    if (pageNum < sumPageNum) {
      state.pageable.pageNum++;
      getTableList("up");
      state.loadingStatus = "loading";
    } else {
      state.loadingStatus = "noMore";
      console.log("最后一页了");
    }
  };

  /**
   * @description 更新分页信息
   * @param {Object} pageable 后台返回的分页数据
   * @return void
   * */
  const updatePageable = (pageable: Table.Pageable) => {
    Object.assign(state.pageable, pageable);
  };

  /**
   * @description 更新查询参数
   * @return void
   * */
  const updatedTotalParam = () => {
    state.totalParam = {};
    // 处理查询参数，可以给查询参数加自定义前缀操作
    let nowSearchParam: Table.StateProps["searchParam"] = {};
    // 防止手动清空输入框携带参数（这里可以自定义查询参数前缀）
    for (let key in state.searchParam) {
      // 某些情况下参数为 false/0 也应该携带参数
      if (state.searchParam[key] || state.searchParam[key] === false || state.searchParam[key] === 0) {
        nowSearchParam[key] = state.searchParam[key];
      }
    }
    Object.assign(state.totalParam, nowSearchParam, isPageable ? pageParam.value : {});
  };

  /**
   * @description 多选数据
   * @return void
   * */
  const setMultipleSelection = item => {
    const { id } = item;
    const index = state.multipleIds.indexOf(id);

    if (index === -1) {
      state.multipleIds.push(id);
      state.multipleSelection.push(item);
    } else {
      state.multipleIds.splice(index, 1);
      state.multipleSelection.splice(index, 1);
    }

    state.checkFlag = state.multipleIds.length === state.tableData.length ? ["全选"] : [];

    selectChange(state.multipleSelection);
  };

  /**
   * @description 全选数据
   * @return void
   * */
  const checkAll = (flag?: ["全选"]) => {
    if (flag[0] !== "全选") {
      state.multipleIds = [];
      state.multipleSelection = [];
    } else {
      state.multipleSelection = JSON.parse(JSON.stringify(state.tableData));
      state.multipleIds = arrJoin3(state.tableData, "id");
    }

    selectChange(state.multipleSelection);
  };

  const isChecked = (id: number) => {
    return state.multipleIds.includes(id) ? "multiple-active iconfont icon-xuanze2" : "multiple iconfont icon-xuanze2";
  };

  /**
   * @description 表格数据查询
   * @return void
   * */
  const search = async () => {
    state.pageable.pageNum = 1;
    updatedTotalParam();
    await getTableList();
  };

  /**
   * @description 表格数据重置
   * @return void
   * */
  const reset = () => {
    // 重置搜索表单的时，如果有默认搜索参数，则重置默认的搜索参数
    Object.assign(state.searchParam, state.searchInitParam);
    search();
  };

  return {
    ...toRefs(state),
    displayLoadMore,
    bottomLoading,
    getTableList,
    search,
    reset,
    updatedTotalParam,
    setMultipleSelection,
    isChecked,
    checkAll
  };
};
